//------------------------------------------------
// maindec.v
//
// James Forrest, 2013
// Based on code by:
// David_Harris@hmc.edu 3 November 2005
//
// Pipelined MIPS processor
//------------------------------------------------

module maindec(input  [5:0] op, funct,
               input  [4:0] rs,
               output       memtoreg, memwrite,
               output       branch,
               output [2:0] compcontrol,
               output       alusrcA, alusrcB,
               output [1:0] regdst,
               output       regwrite, link,
               output [1:0] jump,
               output       signext,
               output [2:0] aluop,

               output       cp0WriteEnable, eret, overflowAble,
               output       addressErrorOnLoadAble, addressErrorOnStoreAble,
               output       badInstruction, cp0ToReg
               );

    reg [24:0] controls;
    assign {regwrite, regdst, alusrcA, alusrcB,   // 1, 2, 1, 1
            branch, compcontrol, memwrite,        // 1, 3, 1
            memtoreg, jump, signext, aluop, link, // 1, 2, 1, 3, 1
            cp0WriteEnable, eret, overflowAble,   // 1, 1, 1
            addressErrorOnLoadAble, addressErrorOnStoreAble, // 1, 1
            cp0ToReg, badInstruction} = controls; // 1, 1
			// signext bit is also used as aluop[3] in the aludec

    always @(*)
        casex(op)
            6'b000000: casex(funct)                              // R-type
                6'b000000: controls <= 25'b1011000000000000000000000; // sll
                6'b00001?: controls <= 25'b1011000000000000000000000; // srl/sra
				6'b001000: controls <= 25'b0000000000010000000000000; // jr
				6'b001001: controls <= 25'b1010000000010000000000000; // jalr
				6'b1000?0: controls <= 25'b1010000000000000000010000; // add/sub
				6'b000100: controls <= 25'b1010000000000000000000000; // sllv
				6'b00011?: controls <= 25'b1010000000000000000000000; // srlv/srav
				6'b1000?1: controls <= 25'b1010000000000000000000000; // addu/subu
				6'b1001??: controls <= 25'b1010000000000000000000000; // and/or/xor/nor
				6'b101010: controls <= 25'b1010000000000000000000000; // slt/sltu
				default:   controls <= 25'bxxxxxxxxxxxxxxxxxxxxxxxx1; // bad instruction
			endcase
            6'b000001: controls <= 25'b0000010000000100100000000; // bltz/bgez
            6'b000100: controls <= 25'b0000010010000100100000000; // BEQ
            6'b000101: controls <= 25'b0000011010000100100000000; // bne
            6'b000110: controls <= 25'b0000010100000100100000000; // blez
            6'b000111: controls <= 25'b0000011100000100100000000; // btgz
            6'b000010: controls <= 25'b0000000000001000000000000; // J
            6'b000011: controls <= 25'b1100000000001000010000000; // jal
            6'b001000: controls <= 25'b1000100000000100000010000; // ADDI
            6'b001001: controls <= 25'b1000100000000100000000000; // addiu
            6'b001010: controls <= 25'b1000100000000101000000000; // slti
            6'b001011: controls <= 25'b1000100000000111000000000; // sltiu
            6'b001100: controls <= 25'b1000100000000000100000000; // andi
            6'b001101: controls <= 25'b1000100000000001000000000; // ori
            6'b001110: controls <= 25'b1000100000000001100000000; // xori
            6'b001111: controls <= 25'b1000100000000101100000000; // lui
            6'b010000: case(rs)
                5'b00000: controls <= 25'b1000000000000000000000010; // mfc0
                5'b00100: controls <= 25'b0000000000000000001000000; // mtc0
                5'b10000: controls <= 25'b0000000000000000000100000; // eret
                default:  controls <= 25'bxxxxxxxxxxxxxxxxxxxxxxxx1; // bad instruction
            endcase
            6'b100011: controls <= 25'b1000100000100100000001000; // LW
            6'b101011: controls <= 25'b0000100001000100000000100; // SW
            default:   controls <= 25'bxxxxxxxxxxxxxxxxxxxxxxxx1; // bad instruction
        endcase
endmodule
